package com.example.flowabledemo.service.impl;

import com.example.flowabledemo.service.LeaveProcessService;

import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.*;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

@Slf4j
@Service("leaveProcessService")
public class LeaveProcessServiceImpl implements LeaveProcessService {
    @Autowired
    private TaskService taskService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ProcessEngine processEngine;

    @Override
    public String startLeaveProcess(String staffId) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("leaveTask", staffId);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("LeaveProcess", map);
        StringBuilder sb = new StringBuilder();
        sb.append("创建请假流程 processId：" + processInstance.getId());
        List<Task> tasks = taskService.createTaskQuery().taskAssignee(staffId).orderByTaskCreateTime().desc().list();
        for (Task task : tasks) {
            sb.append("任务taskId:" + task.getId());
        }
        return sb.toString();

    }

    @Override
    public String queryLeaveProcess(String processId) {

        StringBuilder sb = new StringBuilder();
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
        Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
        sb.append("任务taskId:" + task.getId());
        return sb.toString();

    }


    @Override
    public String applyTask(String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (Objects.isNull(task)) {
            throw new RuntimeException("流程不存在！");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("checkResult", "通过");
        taskService.complete(taskId, map);
        log.info("流程审批通过");
        return "流程审批通过";
    }


    @Override
    public String rejectTask(String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (Objects.isNull(task)) {
            throw new RuntimeException("流程不存在！");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("checkResult", "驳回");
        taskService.complete(taskId, map);
        log.info("流程审批驳回");
        return "流程审批驳回";
    }


    @Override
    public String createProcessDiagramPic(HttpServletResponse httpServletResponse, String processId) throws Exception {

        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
        if (Objects.isNull(pi)) {

            throw new RuntimeException("流程不存在！");
        }

//        Map<String, Object> map = new HashMap<>();
        Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
        List<Execution> executions =
                runtimeService.createExecutionQuery().processInstanceId(task.getProcessInstanceId()).list();

        List<String> activityIds = new ArrayList<>();
        List<String> flows = new ArrayList<>();

        for (Execution exe : executions) {
            List<String> activeActivityIds = runtimeService.getActiveActivityIds(exe.getId());
            activityIds.addAll(activeActivityIds);
        }

        //具体生成流程图步骤
        BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows,
                engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0,false);
        OutputStream out = null;
        byte[] buf = new byte[1024];
        int legth = 0;
        try {
            out = httpServletResponse.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
        return "成功";
    }
}
